﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

using Shared;
using JoltEnvironment.Sql;

namespace LoginServer
{
    public partial class Client
    {
        #region Handler

        /// <summary>
        /// Defines on what position the header is on.
        /// </summary>
        private const int HeaderPoint = 13;

        /// <summary>
        /// Handles an incoming packet for the client.
        /// </summary>
        /// <param name="Packet">Packet to be handled.</param>
        public void HandlePacket(DataPacket Packet)
        {
            if (this.Remains != null)
            {
                byte[] Buffer = new byte[this.Remains.Length + Packet.Buffer.Length];

                Array.Copy(this.Remains, 0, Buffer, 0, this.Remains.Length);
                Array.Copy(Packet.Buffer, 0, Buffer, 0, Packet.Buffer.Length);

                this.Remains = null;
            }

            if (!Packet.VerifyHeaders(this.SessionKey))
            {
                Remains = Packet.Buffer;
            }
            else
            {
                Packet.Pointer = Client.HeaderPoint;
                int Header = Packet.ReadInt32();

                this.PacketTick = (uint)Tick.GetTickCount();

                if ((Packet.Size - Client.HeaderPoint) >= 4)
                {
                    int OldPointer = Packet.Pointer;
                    Packet.Pointer = Packet.Size - 4;

                    this.ClientState = Packet.ReadInt32();

                    Packet.Pointer = OldPointer;
                }

                switch (Header)
                {
                    case MessageHeaders.IN_PING:
                        break;

                    case MessageHeaders.IN_SOCK_FIN:
                        {
                            this.Destruct("Client finished session.");
                        }
                        break;

                    case MessageHeaders.IN_LOGIN:
                        {
                            this.HandleLogin(Packet);
                        }
                        break;

                    default:
                        {
                            this.Write("Unknown packet header received: {0}", Header);
                        }
                        break;
                }
            }
        }

        #endregion

        #region Incoming Handlers

        /// <summary>
        /// Handles a login request from the client.
        /// </summary>
        /// <param name="Packet">Packet that holds login data.</param>
        private void HandleLogin(DataPacket Packet)
        {
            string BuildDate = Packet.ReadString();
            string Username = Packet.ReadString();
            string Password = Packet.ReadString();

            if (BuildDate != Program.Config.Get("Game.Version", "20060629"))
            {
                this.SendError(MessageHeaders.ERROR_VERSION);
            }
            else if (Username.Length > 14 || Username.Length < 3)
            {
                this.SendError(MessageHeaders.ERROR_USERNAME);
            }
            else
            {
                DataRow Account = null;

                using (SqlDatabaseClient Client = Program.DatabaseManager.GetClient())
                {
                    Client.AddParameter("username", Username);

                    Account = Client.ReadDataRow("SELECT * FROM account_tbl WHERE username=@username;");
                }

                if (Account == null)
                {
                    this.SendError(MessageHeaders.ERROR_USERNAME);
                }
                else if ((int)Account["authority"] < 100)
                {
                    this.SendError(MessageHeaders.ERROR_ACCOUNT_BLOCK);
                }
                else if (Password != (string)Account["password"])
                {
                    this.SendError(MessageHeaders.ERROR_PASSWORD);
                }
                else
                {
                    this.UserID = (int)Account["id"];
                    this.Username = Username;
                    this.Password = Password;

                    this.SendServerList();
                }
            }
        }

        #endregion
    }
}
